﻿<%@ WebHandler Language="C#" Class="Apollo.Website.JSONEntityList" %>

using System;
using System.Linq;
using System.Web;
using System.Collections.Generic;
using System.Reflection;
using Apollo;
using Apollo.Core;
using NHibernate;
using NHibernate.Mapping;

namespace Apollo.Website
{
    public class JSONEntityList : IHttpHandler, System.Web.SessionState.IRequiresSessionState
    {
        protected EntityView entityView;
        protected UserView userView;

        public void ProcessRequest(HttpContext context)
        {
            
            context.Response.ContentType = "text/plain";
            context.Response.Cache.SetCacheability(HttpCacheability.NoCache);

            try
            {
                int viewId = 0;
                if (int.TryParse(context.Request["ViewId"], out viewId))
                    entityView = Apollo.Application.Meta<EntityView>()
                                .SingleOrDefault<EntityView>(e => e.Id == viewId);

                if (int.TryParse(context.Request["UserViewId"], out viewId))
                    userView = Apollo.Application.CurrentUserViews.SingleOrDefault<UserView>(u => u.Id == viewId);

                if (entityView != null)
                    GetReponseForView(context, entityView.Entity, entityView.ViewString, entityView.Filter, entityView.OrderBy, entityView.OrderDirection);
                else if (userView != null)
                    GetReponseForView(context, userView.Entity, userView.ViewString, userView.Filter, userView.OrderBy, userView.OrderDirection);
                else
                    throw new ArgumentNullException("Must provide a valid ViewId or UserViewId");
                    //GetDefaultResponse(context);
            }
            catch (Exception ex) {
                Apollo.Application.LogError(ex);
                
                string exMessage = ex.Message.Replace("\r\n", "").Replace("\\", "\\\\").Replace("\"", "\\\"");
                string innerExMessage = ex.InnerException != null ?
                    ex.InnerException.Message.Replace("\n", "").Replace("\\", "\\\\").Replace("\"", "\\\"") : null;
                
                context.Response.Write(
@"
{ 
    ""total"": ""0"", 
    ""page"": ""1"", 
    ""records"": ""0"", 
    ""userdata"": {""error"":""" + exMessage + @""", ""inner_error"": """ + innerExMessage + @"""},
    ""rows"": []
}
");
            }
        }

        protected void GetReponseForView(HttpContext context, Entity entity, string columnsString, string filterString, string orderBy, OrderDirection orderDirection)
        {
            // log current view
            //IUser user = HttpContext.Current.User.Identity as IUser;
            //Apollo.Application.LogError("-usr:" +
            //    (user.Impersonate != null ? user.Name + "[as: " + Application.CurrentUser.Name + "]" : Application.CurrentUser.Name)
            //    + ",entity:" + entity.Name
            //    + ",filter:" + (entity.CurrentFilter ?? "")
            //    + ",quickfilter:" + filterString);
            
            // load entity and persistent class for it
            string columns = !string.IsNullOrEmpty(context.Request["c"]) ? context.Request["c"] : columnsString;

            ProjectionManager manager = new ProjectionManager(columns, entity.MappedClass);

            if (!string.IsNullOrEmpty(context.Request["sidx"]))
                manager.AddOrder(context.Request["sidx"], context.Request["sord"].ToLower() == "asc");
            else if (!string.IsNullOrEmpty(orderBy))
                manager.AddOrder(orderBy, orderDirection == OrderDirection.Asc);

            // add filter
            if (!string.IsNullOrEmpty(entity.CurrentFilter))
                manager.AddFilter(entity.CurrentFilter); // from entity

            if (!string.IsNullOrEmpty(filterString))
                manager.AddFilter(filterString); // from view

            string baseFilter = context.Request["f"];
            if (!string.IsNullOrEmpty(baseFilter))
                manager.AddFilter(baseFilter); // from base

            string filter = context.Request["filters"];
            if (!string.IsNullOrEmpty(filter))
                manager.AddFilter(filter); // from quickfilters or advanced filter

            int recordsPerPage = 20;
            int currentPage = 1;

            if (!string.IsNullOrEmpty(context.Request["rows"]) && !int.TryParse(context.Request["rows"], out recordsPerPage))
                recordsPerPage = 20;
            if (!string.IsNullOrEmpty(context.Request["page"]) && !int.TryParse(context.Request["page"], out currentPage))
                currentPage = 1;

            int records = manager.RowCount();
            int pages = records / recordsPerPage;
            if (pages * recordsPerPage != records)
                pages++;

            
                 
            /*if (records < 50) {
                if (entity.Loading != EntityLoading.LowLoading) {
                    ITransaction tran = Apollo.Application.CurrentSession.BeginTransaction();

                    entity = Apollo.Application.CurrentSession.Get<Entity>(entity.Id);
                    
                    try
                    {
                        entity.Loading = EntityLoading.LowLoading;
                        Apollo.Application.CurrentSession.Save(entity);
                        
                        tran.Commit();
                    }
                    catch { tran.Rollback(); }
                }
            }
            else if (records > 1000000) {
                if (entity.Loading != EntityLoading.HeavyLoading) {
                    ITransaction tran = Apollo.Application.CurrentSession.BeginTransaction();

                    entity = Apollo.Application.CurrentSession.Get<Entity>(entity.Id);

                    try
                    {
                        entity.Loading = EntityLoading.HeavyLoading;
                        Apollo.Application.CurrentSession.Save(entity);

                        tran.Commit();
                    }
                    catch { tran.Rollback(); }
                }
            }*/

            context.Response.Write(@"
{ 
    ""total"": """ + (records == -1 ? (currentPage + 1).ToString() : pages.ToString()) + @""", 
    ""page"": """ + currentPage.ToString() + @""", 
    ""records"": """ + (records == -1 ? "??" : records.ToString()) + @""", 
    ""rows"": [" + manager.ToJSON((currentPage - 1) * recordsPerPage, recordsPerPage) + @"]
} 
");
        }


//        protected void GetDefaultResponse(HttpContext context)
//        {
//            context.Response.Write(@"
//{ 
//    ""total"": ""0"", 
//    ""page"": ""1"", 
//    ""records"": ""0"", 
//    ""rows"": []
//} 
//");
//        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}